Conversation
整合 anomalyco/opencode 上游有价值的 provider 与会话相关修复,按本 fork 架构重新实现: - DeepSeek v4 flash 解禁 variants + Anthropic transform 配置(9d6718131e/56fd16e5c0) - GPT-5 reasoning 变体重构(1cf8123bc):openaiReasoningEfforts 助手化,新增 GPT5_VERSION_RE/PRO_RE/CODEX 等正则与 gpt5Version/versionedGpt5ReasoningEfforts/gpt5CodexReasoningEfforts/gpt5ChatReasoningEfforts 助手;@openrouter / @ai-sdk/azure / @ai-sdk/openai 切换至助手;新增 ai-gateway-provider 路由 - Anthropic & Bedrock transform 保留带签名 reasoning(4e14f7951/233fc5b91) - Anthropic Opus 4.5 efforts(e0396b809)、deep-research 仅 medium(319498e2f)、Mistral medium-2604 加入推理列表(576480b5d) - @ai-sdk/openai-compatible 仅在 GPT5_FAMILY_RE 命中时切换助手(保护 cerebras/togetherai/xai/deepinfra/venice) - Azure SDK 解析助手 selectAzureLanguageModel(c1f607d20) - providerOptions key 按点分割(a12333310) - Bedrock differentModel 时把 reasoning 转 text(29ec07700) - normalizeMessages 入口的 sanitizeSurrogates 全量净化(6409aceb1) - tool 返回纯图片时 text 留空避免 Anthropic 报错(563177c6a) - providers 注册:plugin hooks 在 configProviders 之前执行,让 user config 覆盖 plugin(560baae15) 验证:bun test test/provider/ test/session/message-v2.test.ts → 326 pass / 0 fail;bun typecheck clean
按本 fork 架构重新实现以下上游修复: - provider/error: 重试 server_is_overloaded(25ecf0af6) - tool/read: SUPPORTED_IMAGE_MIMES 白名单,阻止不支持的图片格式内联(51e310c9c) - tool/task: 子 session 继承父级 external_directory 与 deny 规则(d7701dbfb) - skill: OPENCODE_DISABLE_CLAUDE_CODE_SKILLS 仅影响 .claude,不再连带禁用 .agents(ffe0314c4) - core/flag: 解耦 OPENCODE_DISABLE_EXTERNAL_SKILLS 与 OPENCODE_DISABLE_CLAUDE_CODE_SKILLS - format: formatter 子进程 stdin/stdout/stderr 全部 ignore(293bb422f) - cli/providers: auth login 子进程 stderr 改为 inherit(8e016b470) - app/local: 恢复无 model 消息时 msg.model?.variant 链式访问,避免崩溃(9bddf7f3e) 验证:bun typecheck(opencode + core + app)clean; bun test test/tool/task.test.ts test/format/ → 17 pass / 0 fail
记录从 anomalyco/opencode v1.14.30..v1.14.41 抽取的 28 项变更分级(Tier S/A/B/C)、跳过列表与每项 commit hash。已应用 22 项,验证全部通过。
…arch 并行 provider C2 (d9c1838): config 支持从 wellknown 远端 URL 拉取 remote_config 并合并, 支持模板化 headers (env 变量替换)。 C3 (a43d3e0): websearch 抽象出 mcp-websearch 工具底座,新增 Parallel provider 支持,按会话稳定选择 provider,环境变量 OPENCODE_WEBSEARCH_PROVIDER 可覆盖, OPENCODE_ENABLE_PARALLEL flag 启用 Parallel。tui/ui 显示部分按 fork 规则跳过。 验证: bun typecheck clean; bun test test/tool/websearch.test.ts test/config/config.test.ts → 91 pass / 0 fail
filterCompacted 中当尾段消息位于 compaction 摘要之前时,按 [compaction..summary, tail..pre-compaction, summary+1..end] 顺序重排,确保 LLM 看到的语境与时间顺序一致。 同步更新 compaction.test.ts 与 messages-pagination.test.ts 4 处期望断言。
…5e329) A5:用 git 原生 diff --patch 替代手动读取文件 + structuredPatch; 增加 maxOutputBytes 限流(单文件 10MB / 总量 10MB),溢出时输出空 patch。 新增 git.patch/patchAll/patchUntracked/statUntracked 接口,Vcs 层移除 AppFileSystem 依赖。 A4:splitGitPatch 用 (?:^|\n) 分割避免内容中包含 'diff --git' 导致的误切分。 packages/ui 部分按 fork 规则跳过。
Tier S (provider/transform 核心 12 项) + Tier A (小型修复 7 项) + Tier B (工具/技能 3 项) + Tier C (config/websearch 2 项) + REVIEW Minor 修复 3 项。 全程 typecheck 干净,10 个核心测试文件 387+ pass / 0 fail。 延后:A3 (cancel subtask 与 bash 截断 race) / A11/B3 (前端) / B5 (fork 已更严无需) / C1 (bash→shell 重命名)。 详见 .codex_plan/TODO.md。
settings.ts 重构为 HookHandler 多态分派表,支持 command/mcp/http/prompt/agent 五种 handler。8 事件白名单(删除 Notification UI 事件):PreToolUse、 PostToolUse、UserPromptSubmit、SessionStart、SessionEnd、Stop、SubagentStop、 PreCompact。所有 handler 走 Effect.exit 兜底 silent allow,HookSpecificOutput 使用 discriminated union 防 tag 漂移。 agent handler 内置 5 工具 LLM loop(read_file/list_dir/grep/bash 只读白名单/ synthetic_output),MAX_AGENT_TURNS=200,DEFAULT_AGENT_TIMEOUT_MS=60s。bash 工具双层防御:BASH_WHITELIST_SINGLE/PAIR + FORBIDDEN_META 元字符正则;Windows 主动拒绝;MAX_BASH_OUTPUT 8000 字节截断。 session/prompt.ts 兑现 CC 协议三处语义:permissionDecision=deny 短路、 hookSpecificOutput.updatedInput 重写工具入参、UserPromptSubmit additionalContexts 注入 user message。 permission/index.ts 删除 Notification trigger 段(13 行),与 8 事件白名单对齐。 defaultLayer 注入 FetchHttpClient + Provider + Auth + AppFileSystem + CrossSpawnSpawner,agent loop 通过 Effect Service 获取 spawner/fs。 测试:settings.test.ts 51 PASS(12 describe,覆盖 8 事件 × WP-4A/4B/4C/4D-2/4F 矩阵 20/32),agent-tools.test.ts 12 PASS(5 describe)。typecheck 0 错。
- README/AGENTS:新增 Hook System 章节,介绍 5 handler 类型与 Test pattern - replan/02、07、08:Notification 标 "removed in fork(走内部 bus)" - RELEASE_NOTES:9 events → 8 events 口径修正
…ook 动态注入 - WP-5A: SessionStart additionalContexts 真兑现 — 新增 HookStartContext (InstanceState append/consume drain),share/session.ts 在 hook 成功路径 append,prompt.ts 首轮 user message 注入 - WP-5B: continue=false 真短路 — settings.ts trigger 主循环双层 break;prompt.ts 4 个 hook 调用点 + compaction.ts PreCompact 消费 preventContinuation - WP-5C: suppressOutput schema-only no-op 注释 — fork 默认不渲染 hook stdout - WP-5D: Session hook 动态注入 — 新增 SessionHooks Service (add/remove/list/clear);trigger 内合并 sessionEntries + once 自动清理;ctx.isSubAgent 翻译 Stop→SubagentStop(仅影响 session-hook 查找,不动现有静态分发) - 测试:+9 (start-context 2, session-hooks 5, settings WP-5B 2);全量 2361 PASS / 0 回归 - typecheck PASS
- 02-hook-system.md: 阶段 5 已实施段(4-WP 表 + 剩余 WP) - 07-hook-1to1.md: 协议补强段(SessionStart 注入封装 / continue=false / suppressOutput / SessionHooks) - 08-test-plan.md: Phase 5 验收矩阵 + 回归触发器 - RELEASE_NOTES.md: Hook 协议补强(阶段 5)段 - packages/opencode/AGENTS.md: Session-scoped hooks (fork extension) 子节
- WP-6A:trigger 入口加 hasHookForEvent O(1) 短路,无 hook 配置时绕过 matcher 热路径 - WP-6B:Settings 加 allowUntrusted schema 字段 + TODO 注释,等 fork trust 系统接入 - WP-6C:execShell 加 __sourceDir existsSync 预检,缺失时 silent allow(防 GC 竞态误判 deny) 测试:hook 63 PASS(+3)/ 全量 2365 PASS / 0 回归
- 02-hook-system §12: 阶段 6 P1 鲁棒性已实施 - 07-hook-1to1: 性能 / trust / plugin GC 竞态三小节 - 08-test-plan §11: Phase 6 验收矩阵 - RELEASE_NOTES: Hook 协议鲁棒性(阶段 6)段 - AGENTS.md: Hook System 章节加 Performance + Robustness
通过 CC 官方 verbatim 示例 e2e 验证(8/8 PASS),fork 是 CC hook 协议的严格超集 + 2 项行为差异: - 6 项严格超集:case-insensitive matcher / 6 层 settings / hasHookForEvent O(1) 短路 / SessionHooks 动态注入 / __sourceDir GC 保护 / continue=false 双层 break - 1 项 schema-only:allowUntrusted 字段(运行时占位) - 2 项行为差异:suppressOutput 默认翻转(CC=false / fork=true)+ Notification 不支持 验收基线:hook 63 PASS / 全量 2365 PASS / typecheck PASS(1 PRE-EXISTING fail)
invokeMcpHook 此前用整串 "mcp__server__tool" 直接查 mcpSvc.tools() dict,但 src/mcp/index.ts L645 注册时 key 是 sanitize(server)+"_"+sanitize(tool) (无 mcp__ 前缀、单下划线分隔)。两边永远不匹配,type=mcp hook 在 当前 fork 实现下从未真正生效。 修复方案:在 invokeMcpHook 内 strip mcp__ 前缀、按 __ split 出 server/tool、sanitize 后用 _ rejoin 成内部 key 查 dict,保留 tools[command] 作 fallback。对外接受 CC 协议命令名,对内做格式转换。 P6a/P6b e2e 验证:gitnexus + mempalace 真插件经 type=mcp hook 将 envelope 注入 LLM 上下文,模型原文回引 marker 字符串。
graphify Bash hint 与 mempalace Glob|Grep|Read hint 在 bun run dev 启动时 cwd=packages/opencode 下永远 silent skip(相对路径 graphify-out/graph.json 找不到)= 死代码。 project-onboarding skill 严格不做清单 (L116) 已声明此类 hook 不在范围,仓基线归零。
…ug + timeout-kill warn
F4 调研发现 SettingsHook.trigger happy path 零日志输出。Effect.fn 只附 tracing
span 名、不自动 emit log,trigger / runEntry / commandHandler / execShell /
child.on('close') 都未调 log.time 也未 log.info。配合 mempalace 默认命令
'2>/dev/null || true' 的双重静默,hook 执行链对运维完全不可见。
修复(纯日志,不动控制流):
- Fix 1 span 计时:
- trigger 入口加 using _ = log.time('trigger', { event, sessionID })
- runEntry 入口加 using _ = log.time('runEntry', { type, command.slice(0,80) })
- 两个短路点(no_matchers / empty_matchers)加 log.info trigger short-circuit
- Fix 2 spawn lifecycle:
- execShell spawn 前加 log.debug 'hook spawn'(command/cwd/timeoutMs)
- child.on('close') 加 log.debug 'hook close'(exitCode/stdoutLen/stderrLen),
resolve 语义不变
- Fix 3 timeout-kill latent bug:
- exitCode === null 路径之前完全无日志(spawn 设 timeout 触发 SIGTERM 时)
- 新增 log.warn 'hook command timed out / killed (non-blocking)'
Clean-shot 验证 — opencode run echo 命令产出 dev.log 12 行命中:
- SessionStart 完整链路:started → spawn → close → completed duration=54ms
- UserPromptSubmit 短路:started → short-circuit reason=no_matchers → completed 0ms
- Stop 完整链路:started → spawn → close → completed duration=45ms
测试:bun typecheck 0 错;test/hook/ 63/63 PASS;下游 6 套件 184/4skip/0fail。
合规:handler abstraction、trigger reducer 控制流、WP-6C existsSync pre-check
全部保持。无类型/签名/返回值变化。
Fix-1 effect-zod.ts: zod 4.4.3 的 z.toJSONSchema() 把内部 standard-schema spec 的运行时字段 ~standard(含函数引用 validate/vendor/jsonSchema.input 等)当 metadata 一并带出,泄漏到 LLM wire payload 与 16 个 tool snapshot。 返回前 Reflect.deleteProperty(result, '~standard') 顶层 strip。snapshot 自动匹配旧 baseline。 Fix-2 truncate.ts: cleanup 原用 Identifier.timestamp(entry) 比 cutoff,但 id.ts 的进程级单调 clamp(lastTimestamp)会污染 ID 内嵌时间戳——同进程 跨测试或高频写入场景,老文件 ID timestamp 被抬回 ≈ now,cleanup 漏删。 改用 fs.stat(full).mtime 与 Date.now() - RETENTION 比较;保留 catch 容错; mtime Option.None 时回退 +Infinity 保守不删。 测试侧补 utimes:truncation.test.ts cleanup 测试在 writeFileStringScoped 后用 fs.utimes 显式回写 old(-10d) / recent(-3d) mtime,匹配真实生产语义。 验证: - bun typecheck 13/13 PASS - test/tool/ 247/0 fail(含 truncation 19/19、parameters 53/53 含 16 snapshot 匹配旧 baseline) - test/hook/ 63/0、test/session/ 329/0 fail、test/server/ 123/0 fail
z.toJSONSchema() 返回的对象把 ~standard 设为原型链上的不可枚举属性,
Reflect.deleteProperty 对原型链属性返回 false 无效。
本地 Bun snapshot serializer 走 own-enumerable 路径不输出 ~standard,
但 CI 环境的 serializer 通过 for...in 能见到原型属性 — 导致 16 个
parameters 快照在 CI 上 fail 但本地 PASS 的假象。
改用对象展开 {...result} 拷贝 own-enumerable 键,原型回到 Object.prototype,
"~standard" in result === false,本地与 CI 行为一致。
- 删除 src/plugin/github-proxy/ 整个目录(proxy.ts) - 从 plugin/index.ts 注销 GithubProxyAuthPlugin 注册 - 从 provider schema/provider/transform 中剥离 github-proxy 分支 - quota-fetch.ts 收窄 QuotaAuth.provider 为 github-copilot,保留 copilot 计费 TUI 链路完整 - 清理对应测试文件,保留 copilot quota 17 个用例全部通过
- 新增 quota/ 子目录(endpoint.ts / fetch.ts / view.tsx / index.ts)
- proxy 模式 URL = ${provider.github-copilot.api}/quota,parse 扁平 schema
{remaining, entitlement, accounts_active, accounts_total}
- official 模式 URL = api.github.com/copilot_internal/user,parse 嵌套
data.quota_snapshots.premium_interactions
- QuotaInfo 新增 mode: 'proxy'|'official' tag,view 按 accounts_total 分支
- 删除旧 quota.tsx / quota-fetch.ts / quota-fetch.test.ts
- 新增 quota.test.ts 25 用例覆盖双 schema + fetchQuota 全路径
- typecheck 0 error,全量测试 2342 pass,33.110 实调 schema 验证通过
| ), | ||
| ) | ||
| } | ||
| if (urlStr.includes("config.example.com")) { |
…ring sanitization' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
LeXwDeX
pushed a commit
that referenced
this pull request
Jun 7, 2026
…tions + AGPL policy + /dag-worker rename + YAML schema alignment
Consolidated documentation work package combining 5 related changes.
## 1. Multilingual README system (17 languages total)
Translated README.md (zh-Hans primary) into 16 additional languages
using DeepSeek V4 Pro (higher quality than the prior Google Translate
baseline):
- AR (العربية) / BR (Português Brasil) / BS (Bosanski)
- DA (Dansk) / DE (Deutsch) / ES (Español)
- FR (Français) / JA (日本語) / KO (한국어)
- NO (Norsk) / PL (Polski) / RU (Русский)
- TH (ไทย) / TR (Türkçe) / UK (Українська)
Each translation contains:
- Top bilingual switch block linking all 17 languages (current bolded)
- Machine-translation notice banner
- Full translation preserving markdown structure, code fences,
emojis, and technical term literals (opencode, DAG, MIT, AGPL,
LLM, TUI, CJK, IME, SPDX, SaaS, REST, MCP etc.)
- CJK scripts preserve native characters (no romanization)
- UK file excludes Russian-only letters (ы/э/ё) to avoid confusion
- TH file preserves Thai script with natural no-space word breaks
- TR file correctly uses all 6 Turkish special letters (ç/ğ/ı/ş/ö/ü)
- Each file > 10K bytes
ZHT (繁體中文) removed per user decision (simplified Chinese primary
README is considered sufficient for Chinese-speaking users).
## 2. README.md / README_EN.md content expansion
Added 4 new feature sections highlighting self-developed enhancements:
- 🧩 DAG HARNESS 编排任务系统 (AGPL-3.0) — self-developed DAG
workflow engine, capability list, docs cross-links
- 🪝 HOOKS API 超集实现 — 22 runtime events × 5 execution types
with stdin/stdout JSON envelope protocol, DAG event bus
integration notes
- 🛡️ 轻量级 CODING 隔离空间 — Sandbox + Worktree dual-track
isolation for safe code trial runs without polluting real repo
(Sandbox tool ephemeral + DAG Worktree manager auto branch
allocation per parallel node)
- 🔧 中文特性 DEBUG — CJK tokenization / fullwidth punctuation /
Chinese paths / IME interaction fixes
- 🔬 其他小型 DEBUG — back-ported 6 upstream fixes with git commit
references (564cde3 paste corruption, 1124315 paste layout
refresh, fe143df clipboard fallback, e94aeca paste badge
contrast, CJK width estimation, IME jitter)
Added feature summary table at top of the section (5 rows).
### 🔒 AGPL v3 Mandatory License Declaration
New section explicitly stating the fork author's licensing policy:
- Self-authored code MUST use GNU AGPL v3+
- AGPL copyleft requirements on derivative works
- SaaS forced-open-source clause (§13)
- Attribution preservation
- ⚖️ rationale blockquote (AGPL prevents closed-source SaaS
exploitation of open-source community)
### Strengthened upstream disclaimers
Relationship section extended:
- ❌ OpenCode official team does not provide any support, warranty
or endorsement for this fork (per upstream README attribution
requirements)
## 3. Slash command rename: /dagworker → /dag-worker
Align with /dag-ctl's kebab-case convention (强迫症 fix):
- packages/opencode/src/command/index.ts: DAGWORKER: "dag-worker"
(command id) + import ./template/dag-worker.txt
- packages/opencode/src/command/template/dagworker.txt →
dag-worker.txt (file rename + content rewrite in §4 below)
- Cross-references updated in:
- docs/harness-dag.md (1 occurrence)
- packages/opencode/src/command/template/dag-ctl.txt (2 occurrences)
- docs/dag/OVERVIEW.md (9 occurrences + 1 template path reference)
- docs/design/007-dag-session-integration.md (7 occurrences)
- docs/design/008-tui-dag-integration.md (4 occurrences)
- All 17 READMEs (3 occurrences each: DAG Harness entry table +
feature detail + /dag-ctl cross-reference)
Tool id "dagworker" and tool files dagworker.ts / dagworker.txt
NOT renamed — those are the LLM-callable tool artifacts, not slash
commands. Tool-name references in session/system.ts:100
("dagworker status <workflowId>") intentionally left unchanged
because it's the LLM tool invocation, not a slash command.
## 4. dag-worker.txt YAML examples rewritten
The original 6 YAML examples in dag-worker.txt used fictional
schema fields (branches/status/transition_to/task/from_status/
to_status/transition) that did NOT match the actual DAGConfig /
DAGNodeConfig TypeScript interfaces. Replaced with examples that
strictly match real schema fields (name/max_concurrency/nodes/id/
name/dependencies/required/worker_type/worker_config) and each
demonstrates a real DAG rule:
| # | Scenario | Legality | Rule demonstrated |
|---|----------|----------|-------------------|
| 1 | Linear A→B→C chain | ✅ valid | basic DAG structure |
| 2 | Diamond A→(B,C)→D fan-in/out | ✅ valid | parallel scheduling +
max_concurrency |
| 3 | Cycle A→B→A | ❌ invalid | detectCycle rejection
(workflow-engine.ts:287-303) |
| 4 | Dangling dependency ref | ❌ invalid | reference-existence check
(workflow-engine.ts:207-211) |
| 5 | required + optional mixed | ✅ valid | terminal convergence
(workflow-engine.ts:553-575) + workflow status semantic |
| 6 | Duplicate node id in same workflow | ❌ invalid | ID uniqueness
(workflow-engine.ts:206) |
Validate operation list rewritten (dag-worker.txt L34-43) to match
actual RequiredNodesValidator + validateReplanPostConfig logic:
- node.id uniqueness (RequiredNodesValidator L28 + validateReplanPostConfig L206)
- dependencies reference existence (validateReplanPostConfig L207-211)
- cycle detection via detectCycle (L287-303)
- max_concurrency positive integer (validateReplanPostConfig L203-204)
- required node rationality: required node cannot only depend on
optional nodes (warn, not error) (RequiredNodesValidator L47-49)
- required node non-deletable (validateReplanPostConfig L220-226)
- node count upper bound (validateReplanPostConfig L200-201)
- timeout (>0) + retry (>=0) integer sanity (DAGNodeConfig:72-77)
Fictional validators removed: required_nodes completeness (replaced
by node-level required boolean), max_agents limit, max_pushes
limit, shadow route termination, fallback chain cycle check,
worktree isolation policy check, merge strategy compatibility.
SYSTEM.yaml reference (dag-worker.txt L3) deleted entirely — this
file does not exist in the repo; iron law #22 / #28 also do not
exist. Replaced with: "comply with DAG four-principle iron laws
(state machine cannot be bypassed; terminal states irreversible;
events must broadcast; persist-first) — see AGENTS.md".
Configuration format note updated to clarify: YAML serves as
external human-readable declaration format (users may prefer it);
dagworker tool internally takes JSON input (params.workflow:
Schema.String, JSON-parsed inside tool). No YAML→JSON converter
shipped in this commit — documented as known deviation from
design doc intent in docs/dag/OVERVIEW.md (still references YAML
pipeline).
## 5. ZHT language removed
README_ZHT.md deleted. All 17 remaining READMEs' bilingual switch
blocks updated (18 → 17 languages). User decision: simplified
Chinese primary README is sufficient for Chinese-speaking readers.
## Notes
Typecheck: 0 errors.
Session tests: 146 pass / 0 fail / 304 expect() calls.
No production runtime behavior changes (all changes are either in
prompt/template text files, slash command id strings, markdown docs,
or static YAML examples in a template).
The /dag-worker rename does not affect the dagworker tool id (used
by LLMs to invoke the tool directly) — only the slash command
entry point changes.
Upstream attribution preserved: upstream opencode team (sst /
anomalyco) retains MIT copyright on all upstream code; this fork is
independent community enhancement per upstream README's explicit
attribution requirement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.